package cn.z2huo.knowledge.concurrency.contended.falsesharing;

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

/**
 * <p>
 *
 * @author z2huo
 */
@State(Scope.Benchmark)
@BenchmarkMode(Mode.AverageTime)
public class FalseSharingTest {

    private static final long LOOP_COUNT = 1_000_00;

    private static class DataHolder {

//        private volatile long l1 = 0;
//
//        private volatile long l2 = 0;
//
//        private volatile long l3 = 0;
//
//        private volatile long l4 = 0;

        private long l1 = 0;

        private long l2 = 0;

        private long l3 = 0;

        private long l4 = 0;
    }

    private static final DataHolder dataHolder = new DataHolder();

    Thread[] threads;

    @Setup(Level.Invocation)
    public void setup() {
        threads = new Thread[4];
        threads[0] = new Thread(() -> {
            for (long i = 0; i < LOOP_COUNT; i++) {
                dataHolder.l1 += i;
            }
        });
        threads[1] = new Thread(() -> {
            for (long i = 0; i < LOOP_COUNT; i++) {
                dataHolder.l2 += i;
            }
        });
        threads[2] = new Thread(() -> {
            for (long i = 0; i < LOOP_COUNT; i++) {
                dataHolder.l3 += i;
            }
        });
        threads[3] = new Thread(() -> {
            for (long i = 0; i < LOOP_COUNT; i++) {
                dataHolder.l4 += i;
            }
        });
    }

    @Benchmark
    public void test(Blackhole bh) throws InterruptedException {
        for (int i = 0; i < 4; i++) {
            threads[i].start();
        }
        for (int i = 0; i < 4; i++) {
            threads[i].join();
        }
    }

    public static void main(String[] args) throws InterruptedException, RunnerException {

        Options opt = new OptionsBuilder()
                .include(FalseSharingTest.class.getSimpleName())
                .forks(1) // 进程数
                .warmupIterations(2)
                .measurementIterations(2)
                .build();
        new Runner(opt).run();
    }

}
